home *** CD-ROM | disk | FTP | other *** search
- /* ==========
- * NGLList.hh
- * ==========
- *
- * Copyright 1996-2000 Joshua Juran
- */
-
- /*
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
- #pragma once
-
- #include <stddef.h>
-
-
- // NGLListNode
- // -----------
-
- template <class Type>
- class NGLListNode {
- friend class NGLList;
- public:
- NGLListNode(Type inNewDatum)
- : mNext(NULL), mDatum(inNewDatum), mWasDeleted(false) {}
- ~NGLListNode() {}
- void AddNext(Type inNewDatum);
- NGLListNode<Type> *RemoveNext();
- NGLListNode<Type> *Next() const {return mNext;}
- Type Datum() const {return mDatum;}
- bool WasDeleted() const {return mWasDeleted;}
- void MarkDeleted() {mWasDeleted = true;}
- public: // Changed to public because SCpp doesn't know what 'friend' means
- NGLListNode<Type> *mNext;
- Type mDatum;
- bool mWasDeleted;
- };
-
- template <class Type>
- void
- NGLListNode<Type>::AddNext(Type inNewDatum)
- {
- NGLListNode<Type> *node(inNewDatum);
- node->mNext = mNext;
- mNext = node;
- }
-
- template <class Type>
- NGLListNode<Type> *
- NGLListNode<Type>::RemoveNext()
- {
- NGLListNode<Type> *node = mNext;
- mNext = mNext->mNext;
- return node;
- }
-
-
- // NGLList
- // -------
-
- template <class Type>
- class NGLList {
- // For debugging
- private:
- unsigned long mNote;
- public:
- NGLList() : mNote('list'), mHead(NULL), mRefCount(0) {}
- ~NGLList();
-
- protected:
- NGLListNode<Type> *HeadNode() const {return mHead;}
- // No, that's not a typo. No need to zero both of them.
- NGLListNode<Type> *TailNode() const {return mHead ? mTail : NULL;}
- NGLListNode<Type> *FindNode(Type inDatum) const;
-
- public:
- typedef void (*NGLUserFunc)(Type inDatum, void *inUserCon);
-
- public:
- Type FirstDatum() const {return HeadNode() ? HeadNode()->Datum() : NULL;}
- Type LastDatum() const {return TailNode() ? TailNode()->Datum() : NULL;}
- Type Successor(Type inDatum) const {
- return (FindNode(inDatum) && FindNode(inDatum)->Next())
- ? FindNode(inDatum)->Next()->Datum()
- : (Type)NULL;
- }
-
- long Count() const;
- Type GetIndDatum(long inIndex) const;
- void Prepend(Type inNewDatum);
- void Append(Type inNewDatum);
- Type Behead();
- void Remove(Type inVictim);
- void RemoveAll();
- void ForEach(NGLUserFunc inFunc, void *inUserCon);
- NGLListNode<Type> *BeginIteration();
- void EndIteration();
-
- protected:
- NGLListNode<Type> *mHead;
- NGLListNode<Type> *mTail;
- long mRefCount;
- };
-
- // Template class member function definitions
-
- template <class Type>
- NGLList<Type>::~NGLList()
- {
- NGLListNode<Type> *node = mHead;
-
- while (node) {
- NGLListNode<Type> *ondeck = node->Next();
- //Type victim = node->Datum();
- delete node;
- //delete victim;
- node = ondeck;
- }
- }
-
-
- template <class Type>
- NGLListNode<Type> *
- NGLList<Type>::FindNode(Type inDatum) const
- {
- NGLListNode<Type> *node = mHead;
-
- for (node = mHead; node; node = node->Next())
- if (node->Datum() == inDatum)
- return node;
-
- return NULL;
- }
-
-
- template <class Type>
- long
- NGLList<Type>::Count() const
- {
- long count = 0;
- NGLListNode<Type> *node = mHead;
- while (node) {
- count++;
- node = node->Next();
- }
- return count;
- }
-
- template <class Type>
- Type
- NGLList<Type>::GetIndDatum(long inIndex) const
- {
- long count = 0;
- NGLListNode<Type> *node = mHead;
- while (node) {
- if (inIndex-- == 0) {
- return node->Datum();
- }
- node = node->Next();
- }
- return (Type)NULL;
- }
-
- template <class Type>
- void
- NGLList<Type>::Prepend(Type inNewDatum)
- {
- if (!mHead) mHead = mTail = new NGLListNode<Type>(inNewDatum);
- else {
- NGLListNode<Type> *head = new NGLListNode<Type>(inNewDatum);
- head->mNext = mHead;
- mHead = head;
- }
- }
-
-
- template <class Type>
- void
- NGLList<Type>::Append(Type inNewDatum)
- {
- if (!mHead) mHead = mTail = new NGLListNode<Type>(inNewDatum);
- else {
- #if 0
- NGLListNode<Type> *last = mHead;
- while (last->Next())
- last = last->Next();
- last = new NGLListNode<Type>(inNewDatum);
- mTail = last;
- #endif
- mTail->mNext = new NGLListNode<Type>(inNewDatum);
- mTail = mTail->mNext;
- }
- }
-
-
- template <class Type>
- Type
- NGLList<Type>::Behead()
- {
- if (!mHead) return NULL;
- Type datum = mHead->mDatum;
- if (mRefCount > 0) {
- mHead->MarkDeleted();
- } else {
- NGLListNode<Type> *head = mHead;
- mHead = mHead->mNext;
- delete head;
- }
- return datum;
- }
-
-
- template <class Type>
- void
- NGLList<Type>::Remove(Type inVictim)
- {
- // Check for an empty list.
- if (!mHead) return;
-
- NGLListNode<Type> *pred = mHead;
-
- // Check for special case: match on first item.
- if (mHead->Datum() == inVictim) {
- if (mRefCount > 0) {
- pred->MarkDeleted();
- } else {
- mHead = mHead->Next();
- delete pred;
- }
- return;
- }
- while (pred->Next()) { // List of one item stops here.
- if (pred->Next()->Datum() == inVictim) {
- if (mRefCount > 0) {
- pred->Next()->MarkDeleted();
- } else {
- if (pred->Next() == mTail) {
- mTail = pred;
- }
- delete pred->RemoveNext();
- }
- return;
- }
- pred = pred->Next();
- }
- // Couldn't find it.
- }
-
-
- template <class Type>
- void
- NGLList<Type>::RemoveAll()
- {
- if (mRefCount > 0) {
- NGLListNode<Type> *node = mHead;
- while (node) {
- node->MarkDeleted();
- node = node->Next();
- }
- } else {
- while (mHead) {
- NGLListNode<Type> *node = mHead;
- mHead = node->Next();
- delete node;
- }
- }
- }
-
-
- template <class Type>
- void
- NGLList<Type>::ForEach(NGLUserFunc inFunc, void *inUserCon)
- {
- NGLListNode<Type> *node = mHead;
-
- while (node) {
- (*inFunc)(node->Datum(), inUserCon);
- node = node->Next();
- }
- }
-
- template <class Type>
- NGLListNode<Type> *
- NGLList<Type>::BeginIteration()
- {
- mRefCount++;
-
- NGLListNode<Type> *node = mHead;
-
- while (node && node->WasDeleted()) {
- node = node->Next();
- }
-
- return node;
- }
-
- template <class Type>
- void
- NGLList<Type>::EndIteration()
- {
- mRefCount--;
-
- if (mRefCount == 0) {
- // Purge deleted nodes
- while (mHead && mHead->WasDeleted()) {
- NGLListNode<Type> *node = mHead;
- mHead = mHead->Next();
- delete node;
- }
- if (mHead) {
- NGLListNode<Type> *pred = mHead;
- while (pred->Next()) {
- if (pred->Next()->WasDeleted()) {
- if (pred->Next() == mTail) {
- mTail = pred;
- }
- delete pred->RemoveNext();
- } else {
- pred = pred->Next();
- }
- }
- }
- }
- }
-
-